package com.guanyu.u2cache.confinuelife;

import cn.hutool.core.collection.ConcurrentHashSet;
import com.guanyu.u2cache.cache.CacheOperate;
import com.guanyu.u2cache.elect.ElectMaster;
import com.guanyu.u2cache.model.EventData;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.DelayQueue;

/**
 * @author zhouyunjian
 * @date 2023/11/20 14:47
 **/
@Slf4j
@Component
public class CacheLoadListener {

    @Resource
    private CacheReload cacheReload;
    @Resource
    private CacheOperate cacheOperate;
    @Autowired(required = false)
    private ElectMaster electMaster;
    /**
     * 延时队列
     */
    DelayQueue<DelayedTask> delayQueue = new DelayQueue<>();
    /**
     * 数据去除
     */
    Set<String> clearSets = new ConcurrentHashSet<>();

    /**
     * 缓存load加载处理逻辑:
     * 1、清除，则删除队列数据中
     * 2、加载，则放入队列数据中
     *
     * @param invocation
     */
    @EventListener
    @SneakyThrows
    public void onApplicationEvent(CachedInvocation invocation) {
        EventData metaData = invocation.getMetaData();
//        if (EventType.clear.equals(metaData.getEventType())) {
//            clearSets.add(metaData.getKey());
//            return;
//        }
        if (cacheOperate.isExistKey(metaData.getCacheNames(), metaData.getKey(), metaData.getCacheType())) {
            log.debug("已经存在key[{}]无需重复处理", metaData.getKey());
            return;
        }
        if (!electMaster.isMaster()) {
            log.debug("本机不是master，无需对同步事件管理");
            return;
        }
        log.debug("key[{}]接收缓存重载请求", metaData.getKey());
        delayQueue.offer(new DelayedTask(invocation));
    }

    /**
     * 1、读取队列值
     * 2、执行目标方法
     * 3、将结果载入到缓存中
     * 4、重新塞回去
     */
    @SneakyThrows
    @Scheduled(initialDelay = 1000, fixedDelay = 1000 * 5)
    public void refreshCache() {
        while (!delayQueue.isEmpty()) {
            log.debug("队列长度[{}]，获取队列信息", delayQueue.size());
            DelayedTask take = delayQueue.take();
            CachedInvocation invocation = take.getCachedInvocation();
//            if (clearSets.contains(invocation.getMetaData().getKey())) {
//                log.debug("key[{}]已清除，无需重复请求", invocation.getMetaData().getKey());
//                // clearSets.remove(invocation.getMetaData().getKey());
//                continue;
//            }
            cacheReload.reloadCache(invocation, delayQueue);
        }
    }


}
